package com.own.business.irs.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.own.business.irs.model.UserInfoModel;
import com.own.business.irs.property.IrsProperty;
import com.own.business.irs.service.ZlbAuthService;
import com.own.component.common.exception.BusinessException;
import com.own.component.common.util.encrypt.EncryptUtil;
import com.own.component.common.util.encrypt.model.CustomEncryptKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

/**
 * ZlbAuthServiceImpl
 *
 * @author chenxueli
 * @date 2023-07-02 13:31:46
 */
@Slf4j
@Component
public class ZlbAuthServiceImpl implements ZlbAuthService {

    @Resource
    private IrsProperty irsProperty;

    /**
     * 根据票据id获取token
     *
     * @param ticketId 票据id
     * @return token
     */
    @Override
    public String getTokenByTicketId(String ticketId) {
        var property = irsProperty.getLogin();
        var map = getParams();
        // 调用的方法
        map.put("method", "ticketValidation");
        // 票据
        map.put("st", ticketId);
        System.out.println("JSON.toJSONString(map) = " + JSON.toJSONString(map));
        // 执行请求的方法
        var response = HttpRequest.post(property.getUrlTicket())
                .addHeaders(getHeader(property.getUrlTicket()))
                .form(map)
                .contentType("application/x-www-form-urlencoded")
                .execute();
        // 验证请求结果
        var result = checkResponse(response);
        return result.getString("token");
    }

    /**
     * 根据token获取用户信息
     *
     * @param token token
     * @return 用户信息
     */
    @Override
    public UserInfoModel getUserInfoByToken(String token) {
        var property = irsProperty.getLogin();
        var map = getParams();
        // 调用的方法
        map.put("method", "getUserInfo");
        // 票据
        map.put("token", token);
        // 执行请求的方法
        var response = HttpRequest.post(property.getUrlUserInfo())
                .addHeaders(getHeader(property.getUrlUserInfo()))
                .form(map)
                .contentType("application/x-www-form-urlencoded")
                .execute();
        // 验证请求结果
        return new UserInfoModel().ofNormal(checkResponse(response));
    }

    /**
     * 验证响应信息
     *
     * @param response 响应信息
     * @return 响应信息
     */
    private JSONObject checkResponse(HttpResponse response) {
        System.out.println("response.toString() = " + response.toString());
        var body = response.body();
        log.debug("response.body:{}", body);
        if (response.getStatus() != 200) {
            throw new BusinessException("请求异常");
        }
        var object = JSON.parseObject(body);
        if (object.getInteger("result") == 0) {
            return object;
        }
        throw new BusinessException(object.getString("errmsg"));
    }

    private Map<String, String> getHeader(String url) {
        var uriComponents = UriComponentsBuilder.fromHttpUrl(url).build().encode();
        var map = new HashMap<String, String>(16);
        map.put("X-BG-HMAC-ALGORITHM", "hmac-sha256");
        map.put("X-BG-HMAC-ACCESS-KEY", irsProperty.getLogin().getKey());
        var dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        var dateTime = dateFormat.format(new Date());
        map.put("X-BG-DATE-TIME", dateTime);
        // 设置签名信息
        var signature = EncryptUtil.HMAC_SHA_256.encrypt(irsProperty.getLogin().getSecret(), CustomEncryptKey.builder()
                .secret("POST\n" + uriComponents.getPath() + "\n\n" + irsProperty.getLogin().getKey() + "\n" + dateTime + "\n")
                .build());
        map.put("X-BG-HMAC-SIGNATURE", signature);
        return map;
    }

    private Map<String, Object> getParams() {
        var property = irsProperty.getLogin();
        var map = new HashMap<String, Object>(16);
        var formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        var time = LocalDateTime.now().format(formatter);
        // 组件平台的AccessKey
        map.put("servicecode", property.getKey());
        // 数据格式
        map.put("datatype", "json");
        // 时间戳
        map.put("time", time);
        // sign
        map.put("sign", EncryptUtil.MD5.encrypt(property.getKey() + property.getSecret() + time));
        return map;
    }

}
